using System;
using System.Collections.Generic;
using FireStarter.Base;
using FireStarterModeller.BO;
using FireStarterModeller.Logic;
using FireStarterModeller.Test.BO;
using Habanero.Base;
using Habanero.BO;
using Habanero.Util;
using NUnit.Framework;

namespace FireStarterModeller.Test.Logic
{
    [TestFixture]
    public class TestDMRelationshipCreator
    {
        #region Setup/Teardown

        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }

        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [TearDown]
        public virtual void TearDownTest()
        {
        }

        #endregion

        [Test]
        public void Test_Construct()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass);
            //---------------Test Result -----------------------
            Assert.IsNotNull(creator);
            Assert.AreSame(ownerClass, creator.Relationship.ClassDM);
        }

        [Test]
        public void Test_Construct_WhenOwnerClassNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                new DMRelationshipCreator(null);
                Assert.Fail("expected ArgumentNullException");
            }
                //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("ownerClass", ex.ParamName);
            }
        }

        [Test]
        public void Test_SetRelatedClass_ShouldSetUpsRelationshipsRelatedClass()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            DMClass relatedClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            creator.RelatedDMClass = relatedClass;
            //---------------Test Result -----------------------
            Assert.AreSame(relatedClass, creator.Relationship.ReverseRelationship.ClassDM);
        }

        [Test]
        public void Test_SetRelatedClass_Null_ShouldSetUpsRelationshipsRelatedClass()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            creator.RelatedDMClass = null;
            //---------------Test Result -----------------------
            Assert.IsNull(creator.Relationship.ReverseRelationship.ClassDM);
        }

        [Test]
        public void Test_FindRelatedForeignKeyProp_WhenDoesNotHave_ShouldReturnNull()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, relatedClass.Properties.Count);
            DMProperty dmProperty = relatedClass.Properties[0];
            Assert.AreNotEqual(ownerClass.ClassNameBO + "ID", dmProperty.PropertyName);
            Assert.IsNotNull(creator);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = creator.FindRelatedForeignKeyProp();
            //---------------Test Result -----------------------
            Assert.IsNull(foundProperty);
        }

        [Test]
        public void Test_FindRelatedForeignKeyProp_WhenDoesHave_ShouldReturnFKProp()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(relatedClass);
            property.PropertyName = ownerClass.ClassNameBO + "ID";
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, relatedClass.Properties.Count);
            Assert.AreEqual(ownerClass.ClassNameBO + "ID", property.PropertyName);
            Assert.IsNotNull(creator);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = creator.FindRelatedForeignKeyProp();
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(property, foundProperty);
        }

        [Test]
        public void Test_FindRelatedForeignKeyProp_WhenOwnerIDPropNameMatchesPropInRelatedClass_ShouldReturnFKProp_BUG269()
        {
            //When the ID property of the Business object is not conventional
            // by convention the IDProp is ClassName + "ID" but in cases where the 
            // Primary and Foreign Key follow a different naming convention 
            // you should still be able to Find the ForeignKey.
            // REDMINE ISSUE: Issue #269
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            var primaryKeyProp = ownerClass.ObjectIdentity.Properties[0];
            primaryKeyProp.PropertyName = TestUtilsShared.GetRandomString();
            DMProperty foreignKeyProp = TestUtilsDMProperty.CreateUnsavedValidDMProperty(relatedClass);
            foreignKeyProp.PropertyName = primaryKeyProp.PropertyName;
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, relatedClass.Properties.Count);
            Assert.AreEqual(primaryKeyProp.PropertyName, foreignKeyProp.PropertyName);
            Assert.IsNotNull(creator);
            //---------------Execute Test ----------------------
            DMProperty foundFKProperty = creator.FindRelatedForeignKeyProp();
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundFKProperty);
            Assert.AreSame(foreignKeyProp, foundFKProperty);
        }

        [Test]
        public void Test_FindRelatedForeignKeyProp_WhenRelatedClassNull_ShouldReturnNull()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            TestUtilsShared.CreateSavedObjectIdentityInfo(ownerClass);
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass);
            //---------------Assert Precondition----------------
            Assert.IsNull(creator.Relationship.RelatedClass);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = creator.FindRelatedForeignKeyProp();
            //---------------Test Result -----------------------
            Assert.IsNull(foundProperty);
        }
        [Test]
        public void Test_CanFindForeignKey_WhenDoesHave_ShouldReturnFalse()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(relatedClass);
            property.PropertyName = ownerClass.ClassNameBO + "ID";
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, relatedClass.Properties.Count);
            Assert.AreEqual(ownerClass.ClassNameBO + "ID", property.PropertyName);
            Assert.IsNotNull(creator);
            //---------------Execute Test ----------------------
            bool foundProperty = creator.CanFindForeignKey;
            //---------------Test Result -----------------------
            Assert.IsTrue(foundProperty);
        }

        [Test]
        public void Test_CanFindForeignKey_WhenDoesHave_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(relatedClass);
            property.PropertyName = ownerClass.ClassNameBO + "ID";
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, relatedClass.Properties.Count);
            Assert.AreEqual(ownerClass.ClassNameBO + "ID", property.PropertyName);
            Assert.IsNotNull(creator);
            //---------------Execute Test ----------------------
            bool foundProperty = creator.CanFindForeignKey;
            //---------------Test Result -----------------------
            Assert.IsTrue(foundProperty);
        }
        [Test]
        public void Test_CanFindForeignKey_WhenHasHaveOwner_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            property.PropertyName = relatedClass.ClassNameBO + "ID";
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, ownerClass.Properties.Count);
            Assert.AreEqual(relatedClass.ClassNameBO + "ID", property.PropertyName);
            Assert.IsNotNull(creator);
            //---------------Execute Test ----------------------
            bool foundProperty = creator.CanFindForeignKey;
            //---------------Test Result -----------------------
            Assert.IsTrue(foundProperty);
        }

        [Test]
        public void Test_SetUpRelationship_WhenFindForeignKeyProp_ShouldSetupRelationshipNameAndCardinality()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(relatedClass);
            property.PropertyName = ownerClass.ClassNameBO + "ID";
            DMProperty foundProperty = creator.FindRelatedForeignKeyProp();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(property, foundProperty);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(Cardinality.Multiple, creator.Relationship.Cardinality);
            Assert.AreEqual(StringUtilities.Pluralize(relatedClass.ClassNameBO), creator.Relationship.RelationshipName);
            //Reverse Relationship
            Assert.AreEqual(Cardinality.Single, creator.Relationship.ReverseRelationship.Cardinality);
            Assert.AreEqual(StringUtilities.Singularize(ownerClass.ClassNameBO),
                            creator.Relationship.ReverseRelationship.RelationshipName);
        }

        [Test]
        public void Test_FindForeignKey_WhenAlreadyHasRelationshipForFKProp_ShouldReturnNull()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(relatedClass);
            property.PropertyName = ownerClass.ClassNameBO + "ID";
            Assert.AreEqual(0, property.RelationshipProperties.Count);
            creator.SetupRelationship();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, property.RelationshipProperties.Count);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = creator.FindRelatedForeignKeyProp();
            //---------------Test Result -----------------------
            Assert.IsNull(foundProperty);
        }

        [Test]
        public void Test_SetUpRelationship_WhenFindForeignKeyProp_ShouldSetupRelationshipRelatedProps()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(relatedClass);
            property.PropertyName = ownerClass.ClassNameBO + "ID";
            DMProperty foundProperty = creator.FindRelatedForeignKeyProp();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(property, foundProperty);
            Assert.IsFalse(creator.MustCreateForeignKeyProp);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, creator.Relationship.RelationshipProperties.Count);
            DMRelationshipProperty relationshipProperty = creator.Relationship.RelationshipProperties[0];
            Assert.AreSame(property, relationshipProperty.RelatedProperty);
            Assert.AreSame(ownerClass.ObjectIdentity.Properties[0], relationshipProperty.OwnerProperty);
        }

        [Test]
        public void Test_SetUpRelationship_WhenNoForeignKey_MustCreateFKFalse_ShouldNotCreateRelationshipProps()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty foundProperty = creator.FindRelatedForeignKeyProp();
//            creator.RelationshipCardinality = RelationshipCardinality.ManyToOne;
            creator.RelationshipCardinality = RelationshipCardinality.ManyToOne;
            //---------------Assert Precondition----------------
            Assert.IsNull(foundProperty);
            Assert.IsFalse(creator.MustCreateForeignKeyProp);
            Assert.AreEqual(RelationshipCardinality.ManyToOne, creator.RelationshipCardinality);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(0, creator.Relationship.RelationshipProperties.Count);
            Assert.AreEqual(Cardinality.Single, creator.Relationship.Cardinality);
            Assert.IsNotNull(creator.Relationship.RelationshipName);
            Assert.AreEqual(0, creator.Relationship.RelationshipProperties.Count);
            //Reverse Relationship
            Assert.AreEqual(Cardinality.Multiple, creator.Relationship.ReverseRelationship.Cardinality);
            Assert.IsNotNull(creator.Relationship.ReverseRelationship.RelationshipName);
            Assert.AreEqual(0, ((DMRelationship)creator.Relationship.ReverseRelationship).RelationshipProperties.Count);
        }

        [Test]
        public void Test_FindOwnerForeignKeyProp_WhenDoesNotHave_ShouldReturnNull()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, ownerClass.Properties.Count);
            DMProperty dmProperty = ownerClass.Properties[0];
            Assert.AreNotEqual(relatedClass.ClassNameBO + "ID", dmProperty.PropertyName);
            Assert.IsNotNull(creator);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = creator.FindOwnerForeignKeyProp();
            //---------------Test Result -----------------------
            Assert.IsNull(foundProperty);
        }

        [Test]
        public void Test_FindOwnerForeignKeyProp_WhenDoesHave_ShouldReturnFKProp()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            property.PropertyName = relatedClass.ClassNameBO + "ID";
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, ownerClass.Properties.Count);
            Assert.AreEqual(relatedClass.ClassNameBO + "ID", property.PropertyName);
            Assert.IsNotNull(creator);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = creator.FindOwnerForeignKeyProp();
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(property, foundProperty);
        }

        [Test]
        public void Test_FindOwnerForeignKeyProp_WhenRelatedClassNull_ShouldReturnNull()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            TestUtilsShared.CreateSavedObjectIdentityInfo(ownerClass);
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass);
            //---------------Assert Precondition----------------
            Assert.IsNull(creator.Relationship.RelatedClass);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = creator.FindOwnerForeignKeyProp();
            //---------------Test Result -----------------------
            Assert.IsNull(foundProperty);
        }


        [Test]
        public void Test_SetUpRelationship_WhenFindOwnerForeignKeyPropTrue_ShouldSetupRelationshipNameAndCardinality()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            property.PropertyName = relatedClass.ClassNameBO + "ID";
            DMProperty foundProperty = creator.FindOwnerForeignKeyProp();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(property, foundProperty);
            Assert.IsNull(creator.FindRelatedForeignKeyProp());
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(Cardinality.Single, creator.Relationship.Cardinality);
            Assert.AreEqual(StringUtilities.Singularize(relatedClass.ClassNameBO), creator.Relationship.RelationshipName);
            //Reverse Relationship
            IDMRelationship reverseRelationship = creator.Relationship.ReverseRelationship;
            Assert.AreEqual(Cardinality.Multiple, reverseRelationship.Cardinality);
            Assert.AreEqual(StringUtilities.Pluralize(ownerClass.ClassNameBO), reverseRelationship.RelationshipName);
        }

        [Test]
        public void Test_SetUpRelationship_WhenFindOwnerForeignKeyPropTrue_ShouldSetupRelationshipRelatedProps()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            property.PropertyName = relatedClass.ClassNameBO + "ID";
            DMProperty foundProperty = creator.FindOwnerForeignKeyProp();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(property, foundProperty);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, creator.Relationship.RelationshipProperties.Count);
            DMRelationshipProperty relationshipProperty = creator.Relationship.RelationshipProperties[0];
            Assert.AreSame(relatedClass.ObjectIdentity.Properties[0], relationshipProperty.RelatedProperty);
            Assert.AreSame(property, relationshipProperty.OwnerProperty);
        }

        [Test]
        public void Test_SetUpRelationship_WhenNoForeignKeyOnEitherClass_ShouldNotCreateRelationshipProps()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = false;
            creator.RelationshipCardinality = RelationshipCardinality.OneToMany;
            //---------------Assert Precondition----------------
            Assert.IsFalse(creator.CanFindForeignKey);
            Assert.IsTrue(creator.CanCreateForeignKey);
            Assert.IsFalse(creator.MustCreateForeignKeyProp);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(0, creator.Relationship.RelationshipProperties.Count);
            AssertCardinalityMultiple(creator);
            Assert.IsNotNull(creator.Relationship.RelationshipName);

            //Reverse Relationship
            Assert.AreEqual(Cardinality.Single, creator.Relationship.ReverseRelationship.Cardinality);
            Assert.IsNotNull(creator.Relationship.ReverseRelationship.RelationshipName);
        }
        [Test]
        public void Test_SetUpRelationship_WhenNoForeignKeyOnEitherClass_OneToOne_ShouldCreateRelationship()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = false;
            creator.RelationshipCardinality = RelationshipCardinality.OneToOne;
            //---------------Assert Precondition----------------
            Assert.IsFalse(creator.CanFindForeignKey);
            Assert.IsTrue(creator.CanCreateForeignKey);
            Assert.IsFalse(creator.MustCreateForeignKeyProp);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            var relationship = creator.Relationship;
            AssertCardinalitySingle(relationship);
            Assert.IsNotNull(relationship.RelationshipName);
            Assert.AreEqual(relatedClass.ClassNameBO, relationship.RelationshipName);

            //Reverse Relationship
            var reverseRelationship = relationship.ReverseRelationship;
            AssertCardinalitySingle(reverseRelationship);
            Assert.IsNotNull(reverseRelationship.RelationshipName);
            Assert.AreEqual(ownerClass.ClassNameBO, reverseRelationship.RelationshipName);
        }

        [Test]
        public void Test_SetCreateForeignKeyProp()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = false;
            //---------------Assert Precondition----------------
            Assert.IsFalse(creator.MustCreateForeignKeyProp);
            //---------------Execute Test ----------------------
            creator.MustCreateForeignKeyProp = true;
            //---------------Test Result -----------------------
            Assert.IsTrue(creator.MustCreateForeignKeyProp);
        }

        [Test]
        public void Test_SetCardinality()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = false;
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(RelationshipCardinality.OneToMany, creator.RelationshipCardinality);
            //---------------Execute Test ----------------------
            creator.RelationshipCardinality = RelationshipCardinality.OneToMany;
            //---------------Test Result -----------------------
            Assert.AreEqual(RelationshipCardinality.OneToMany, creator.RelationshipCardinality);
        }

        [Test]
        public void Test_SetUpRelationship_WhenNoFKOnEitherClass_WhenMustCreateFK_WhenManyToMany_ShouldCreatePropAndRelationshipProp()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = true;
            creator.RelationshipCardinality = RelationshipCardinality.OneToMany;
            //---------------Assert Precondition----------------
            Assert.IsNull(creator.FindOwnerForeignKeyProp());
            Assert.IsNull(creator.FindRelatedForeignKeyProp());
            Assert.IsTrue(creator.MustCreateForeignKeyProp);
            Assert.AreEqual("System.Guid", ownerClass.ObjectIdentity.Properties[0].PropertyTypeString);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            BusinessObjectCollection<DMRelationshipProperty> relationshipProperties =
                creator.Relationship.RelationshipProperties;
            Assert.AreEqual(1, relationshipProperties.Count);
            AssertCardinalityMultiple(creator);
            Assert.AreEqual(StringUtilities.Pluralize(relatedClass.ClassNameBO), creator.Relationship.RelationshipName);

            IDMRelationship reverseRelationship = creator.Relationship.ReverseRelationship;
            Assert.AreEqual(Cardinality.Single, creator.Relationship.ReverseRelationship.Cardinality);
            Assert.AreEqual(StringUtilities.Singularize(ownerClass.ClassNameBO), reverseRelationship.RelationshipName);
            IDMProperty relatedProperty = relationshipProperties[0].RelatedProperty;
            Assert.AreEqual(ownerClass.ClassNameBO + "ID", relatedProperty.PropertyName);
            DMProperty boProp = ownerClass.ObjectIdentity.Properties[0];
            Assert.AreEqual(boProp.PropertyType, relatedProperty.PropertyType);
        }

        [Test]
        public void Test_SetUpRelationship_WhenNoFKOnEitherClass_WhenMustCreateFK_WhenOneToOne_ShouldCreatePropAndRelationshipProp()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            CreateTwoSavedBOs(out ownerClass, out relatedClass);
            DMRelationshipCreator creator1 = new DMRelationshipCreator(ownerClass) {RelatedDMClass = relatedClass};
            DMRelationshipCreator creator = creator1;
            creator.MustCreateForeignKeyProp = true;
            creator.RelationshipCardinality = RelationshipCardinality.OneToOne;

            //---------------Assert Precondition----------------
            Assert.IsNull(creator.FindOwnerForeignKeyProp());
            Assert.IsNull(creator.FindRelatedForeignKeyProp());
            Assert.IsTrue(creator.MustCreateForeignKeyProp);
            var ownerClassPKProp = ownerClass.ObjectIdentity.Properties[0];
            Assert.AreEqual("System.Guid", ownerClassPKProp.PropertyTypeString);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------

            AssertCardinalitySingle(creator.Relationship);
            Assert.AreEqual(StringUtilities.Singularize(relatedClass.ClassNameBO), creator.Relationship.RelationshipName);

            IDMRelationship reverseRelationship = creator.Relationship.ReverseRelationship;
            AssertCardinalitySingle(reverseRelationship);
            Assert.AreEqual(StringUtilities.Singularize(ownerClass.ClassNameBO), reverseRelationship.RelationshipName);


            BusinessObjectCollection<DMRelationshipProperty> relationshipProperties =
                creator.Relationship.RelationshipProperties;
            Assert.AreEqual(1, relationshipProperties.Count);
            var relationshipProp = relationshipProperties[0];
            IDMProperty relatedProperty = relationshipProp.RelatedProperty;
            Assert.AreEqual(ownerClass.ClassNameBO + "ID", relatedProperty.PropertyName);
            Assert.IsTrue(relatedProperty.Status.IsNew);

            Assert.AreEqual(ownerClassPKProp.PropertyName, relationshipProp.OwnerProperty.PropertyName);

            DMProperty boProp = ownerClassPKProp;
            Assert.AreEqual(boProp.PropertyType, relatedProperty.PropertyType);
        }

        [Test]
        public void Test_SetUpRelationship_WhenNoFKs_AndMustCreateFK_AndOneToOne_ShouldSetCreatedPropAsUC()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            CreateTwoSavedBOs(out ownerClass, out relatedClass);
            DMRelationshipCreator creator1 = new DMRelationshipCreator(ownerClass) {RelatedDMClass = relatedClass};
            DMRelationshipCreator creator = creator1;
            creator.MustCreateForeignKeyProp = true;
            creator.RelationshipCardinality = RelationshipCardinality.OneToOne;

            //---------------Assert Precondition----------------
            Assert.IsNull(creator.FindOwnerForeignKeyProp());
            Assert.IsNull(creator.FindRelatedForeignKeyProp());
            Assert.IsTrue(creator.MustCreateForeignKeyProp);
            var ownerClassPKProp = ownerClass.ObjectIdentity.Properties[0];
            Assert.AreEqual("System.Guid", ownerClassPKProp.PropertyTypeString);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            BusinessObjectCollection<DMRelationshipProperty> relationshipProperties =
                creator.Relationship.RelationshipProperties;
            var relationshipProp = relationshipProperties[0];
            IDMProperty relatedProperty = relationshipProp.RelatedProperty;

            Assert.AreEqual(1, relatedClass.UniqueConstraints.Count);
            var uniqueConstraint = relatedClass.UniqueConstraints[0];
            Assert.AreEqual(relatedProperty.PropertyName, uniqueConstraint.UniqueConstraintName);
            Assert.IsTrue(relatedProperty.IsPartOfSingleUniqueConstraint);
        }

        private static void CreateTwoSavedBOs(out DMClass ownerClass, out DMClass relatedClass)
        {
            ownerClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            TestUtilsShared.CreateSavedObjectIdentityInfo(ownerClass);
            relatedClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            TestUtilsShared.CreateSavedObjectIdentityInfo(relatedClass);
            ownerClass.Save();
            relatedClass.Save();
        }

        [Test]
        public void Test_CancelCreatedProps_WhenCreatedRelatedFK_ShouldRemoveCreatedPropsAndShouldNotCancelEditsOnClass()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = true;
            creator.RelationshipCardinality = RelationshipCardinality.OneToMany;
            creator.SetupRelationship();
            BusinessObjectCollection<DMRelationshipProperty> relationshipProperties = creator.Relationship.RelationshipProperties;
            DMRelationship reverseRelationship = (DMRelationship) creator.Relationship.ReverseRelationship;
            const string newTableName = "NewName";
            relatedClass.MappedTableName = newTableName;
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, relationshipProperties.Count);
            Assert.AreEqual(StringUtilities.Singularize(ownerClass.ClassNameBO), reverseRelationship.RelationshipName);
            Assert.AreEqual(2, relatedClass.Properties.Count);
            Assert.AreEqual(newTableName, relatedClass.MappedTableName);
            //---------------Execute Test ----------------------
            creator.CancelCreatedProperties();
            //---------------Test Result -----------------------
            Assert.IsNull(creator.Relationship.RelationshipName);
            Assert.IsNull(reverseRelationship.RelationshipName);
            Assert.AreEqual(0, creator.Relationship.RelationshipProperties.Count);
            Assert.AreEqual(0, reverseRelationship.RelationshipProperties.Count);
            Assert.AreEqual(1, relatedClass.Properties.Count);
            Assert.AreEqual(newTableName, relatedClass.MappedTableName);
        }
        [Test]
        public void Test_CancelCreatedProps_WhenCreatedRelatedFK_ShouldRemoveRelatedPropsAndShouldNotRemoveRelatedClassProps()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(relatedClass);
            property.PropertyName = ownerClass.ClassNameBO + "ID";
            DMProperty foundProperty = creator.FindRelatedForeignKeyProp();
            foundProperty.Save();
            Assert.AreEqual(0, foundProperty.RelationshipProperties.Count);
            creator.SetupRelationship();
            //---------------Assert Precondition----------------

            Assert.IsNotNull(foundProperty);
            Assert.AreEqual(1, creator.Relationship.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsDeleted);
            Assert.AreEqual(2,relatedClass.Properties.Count);
            Assert.AreEqual(1, foundProperty.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsNew);
            //---------------Execute Test ----------------------
            creator.CancelCreatedProperties();
            //---------------Test Result -----------------------
            Assert.IsNull(creator.Relationship.RelationshipName);

            Assert.AreEqual(0, creator.Relationship.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsDeleted);
            Assert.AreEqual(2, relatedClass.Properties.Count);
            Assert.AreEqual(0, foundProperty.RelationshipProperties.Count);
        }
        [Test]
        public void Test_CancelCreatedProps_WhenFKPropOn()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            property.PropertyName = relatedClass.ClassNameBO + "ID";
            DMProperty foundProperty = creator.FindOwnerForeignKeyProp();
            foundProperty.Save();
            Assert.AreEqual(0, foundProperty.RelationshipProperties.Count);
            creator.SetupRelationship();
            //---------------Assert Precondition----------------

            Assert.IsNotNull(foundProperty);
            Assert.AreEqual(1, creator.Relationship.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsDeleted);
            Assert.AreEqual(2, ownerClass.Properties.Count);
            Assert.AreEqual(1, foundProperty.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsNew);
            //---------------Execute Test ----------------------
            creator.CancelCreatedProperties();
            //---------------Test Result -----------------------
            Assert.IsNull(creator.Relationship.RelationshipName);

            Assert.AreEqual(0, creator.Relationship.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsDeleted);
            Assert.AreEqual(2, ownerClass.Properties.Count);
            Assert.AreEqual(0, foundProperty.RelationshipProperties.Count);
        }

        [Test]
        public void Test_CancelAllEdits_ShouldCancelAllPropsCreatedAndRemoveRelationshipFromClass()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            property.PropertyName = relatedClass.ClassNameBO + "ID";
            DMProperty foundProperty = creator.FindOwnerForeignKeyProp();
            foundProperty.Save();
            Assert.AreEqual(0, foundProperty.RelationshipProperties.Count);
            creator.SetupRelationship();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundProperty);
            Assert.AreEqual(1, creator.Relationship.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsDeleted);
            Assert.AreEqual(2, ownerClass.Properties.Count);
            Assert.AreEqual(1, foundProperty.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsNew);
            //---------------Execute Test ----------------------
            creator.CancelAllEdits();
            //---------------Test Result -----------------------
            Assert.IsNull(creator.Relationship.RelationshipName);

            Assert.AreEqual(0, creator.Relationship.RelationshipProperties.Count);
            Assert.IsFalse(foundProperty.Status.IsDeleted);
            Assert.AreEqual(2, ownerClass.Properties.Count);
            Assert.AreEqual(0, foundProperty.RelationshipProperties.Count);

            Assert.IsNull(creator.Relationship.RelatedClass);
            Assert.IsNull(creator.Relationship.OwnerClass);
            Assert.IsNull(creator.Relationship.ReverseRelationship.OwnerClass);
            Assert.IsNull(creator.Relationship.ReverseRelationship.OwnerClass);
        }
        [Test]
        public void Test_SetUpRelationship_WhenOneToMany_ShouldSetReverseRelationshipDeleteActionDoNothing()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = true;
            creator.RelationshipCardinality = RelationshipCardinality.OneToMany;
            //---------------Assert Precondition----------------
            Assert.AreEqual(RelationshipCardinality.OneToMany, creator.RelationshipCardinality);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------

            DMRelationship relationship = creator.Relationship;
            Assert.AreEqual(Cardinality.Multiple, relationship.Cardinality);
            Assert.AreEqual(DeleteParentAction.Prevent, relationship.DeleteAction);
            IDMRelationship reverseRelationship = relationship.ReverseRelationship;
            Assert.AreEqual(Cardinality.Single, reverseRelationship.Cardinality);
            Assert.AreEqual(DeleteParentAction.DoNothing, reverseRelationship.DeleteAction);
        }

        [Test]
        public void Test_SetUpRelationship_WhenManyToOne_WhenNoFKOnEitherClass_WhenMustCreateFK_ShouldCreatePropOnOwnerClass()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = true;
            creator.RelationshipCardinality = RelationshipCardinality.ManyToOne;
            //---------------Assert Precondition----------------
            Assert.IsNull(creator.FindOwnerForeignKeyProp());
            Assert.IsNull(creator.FindRelatedForeignKeyProp());
            Assert.IsTrue(creator.MustCreateForeignKeyProp);
            Assert.AreEqual("System.Guid", ownerClass.ObjectIdentity.Properties[0].PropertyTypeString);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(Cardinality.Single, creator.Relationship.Cardinality);
            Assert.AreEqual(StringUtilities.Singularize(relatedClass.ClassNameBO), creator.Relationship.RelationshipName);

            IDMRelationship reverseRelationship = creator.Relationship.ReverseRelationship;
            AssertCardinalityMultiple((DMRelationship) reverseRelationship);
            Assert.AreEqual(StringUtilities.Pluralize(ownerClass.ClassNameBO), reverseRelationship.RelationshipName);


            BusinessObjectCollection<DMRelationshipProperty> relationshipProperties =
                creator.Relationship.RelationshipProperties;
            Assert.AreEqual(1, relationshipProperties.Count);
            IDMProperty ownerProperty = relationshipProperties[0].OwnerProperty;
            Assert.AreEqual(relatedClass.ClassNameBO + DMRelationshipCreator.FkPropertySuffix,
                            ownerProperty.PropertyName);

            DMProperty relatedProp = relatedClass.ObjectIdentity.Properties[0];
            Assert.AreEqual(relatedProp.PropertyTypeString, ownerProperty.PropertyTypeString);

            Assert.AreEqual(1, relationshipProperties.Count);
            DMRelationshipProperty dmRelationshipProperty = relationshipProperties[0];
            Assert.IsNotNull(dmRelationshipProperty.OwnerProperty);
            Assert.IsNotNull(dmRelationshipProperty.RelatedProperty);
            Assert.AreSame(ownerProperty, dmRelationshipProperty.OwnerProperty);
            Assert.AreSame(relatedProp, dmRelationshipProperty.RelatedProperty);
        }

        [Test]
        public void Test_SetUpRelationship_WhenSingle_ShouldSetRelationshipDeleteActionDoNothing()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.MustCreateForeignKeyProp = true;
            creator.RelationshipCardinality = RelationshipCardinality.ManyToOne;
            //---------------Assert Precondition----------------
            AssertRelationshipCardinalityManyToOne(creator);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            DMRelationship relationship = creator.Relationship;
            Assert.AreEqual(Cardinality.Single, relationship.Cardinality);
            Assert.AreEqual(DeleteParentAction.DoNothing, relationship.DeleteAction);
            Assert.AreEqual(StringUtilities.Singularize(relatedClass.ClassNameBO), relationship.RelationshipName);


            IDMRelationship reverseRelationship = relationship.ReverseRelationship;
            AssertCardinalityMultiple((DMRelationship) reverseRelationship);
            Assert.AreEqual(StringUtilities.Pluralize(ownerClass.ClassNameBO), reverseRelationship.RelationshipName);
            Assert.AreEqual(DeleteParentAction.Prevent, reverseRelationship.DeleteAction);
        }

        [Test]
        public void Test_CreateFKProperty_ShouldCreateProp()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreatorStub creator = CreateCreatorStubWithTwoClasses(out ownerClass, out relatedClass);
            //---------------Assert Precondition----------------
            Assert.IsNull(creator.FindOwnerForeignKeyProp());
            Assert.IsNull(creator.FindRelatedForeignKeyProp());
            const string expectedType = "System.Guid";
            Assert.AreEqual(expectedType, ownerClass.ObjectIdentity.Properties[0].PropertyTypeString);
            //---------------Execute Test ----------------------
            DMProperty createdProp = creator.TestCreateFKProperty(ownerClass, relatedClass);
            //---------------Test Result -----------------------
            Assert.IsNotNull(createdProp);
            Assert.AreEqual(expectedType, createdProp.PropertyTypeString);
            Assert.AreEqual(ownerClass.ClassNameBO + DMRelationshipCreator.FkPropertySuffix, createdProp.PropertyName);
            Assert.IsTrue(relatedClass.Properties.Contains(createdProp));
        }

        [Test]
        public void Test_AreObjectIDsValid_WhenRelationshipAreObjectIDsValid_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            //---------------Assert Precondition----------------
            Assert.IsTrue(creator.Relationship.AreObjectIDsValid);
            //---------------Execute Test ----------------------
            var areObjectIDsValid = creator.AreObjectIDsValid;
            //---------------Test Result -----------------------
            Assert.IsTrue(areObjectIDsValid);
       }
        [Test]
        public void Test_AreObjectIDsValid_WhenRelationshipNotAreObjectIDsValid_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            ownerClass.ObjectIdentity.Properties.RemoveAll(property => true);
            //---------------Assert Precondition----------------
            Assert.IsFalse(creator.Relationship.AreObjectIDsValid);
            //---------------Execute Test ----------------------
            var areObjectIDsValid = creator.AreObjectIDsValid;
            //---------------Test Result -----------------------
            Assert.IsFalse(areObjectIDsValid);
        }

        [Test]
        public void Test_CanCreateForeignKey_WhenAreObjectsIDValidAndCanFindForeignKey_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            property.PropertyName = relatedClass.ClassNameBO + "ID";
            property.Save();
            //---------------Assert Precondition----------------
            Assert.IsTrue(creator.Relationship.AreObjectIDsValid);
            Assert.IsTrue(creator.CanFindForeignKey);
            //---------------Execute Test ----------------------
            var canCreateFK = creator.CanCreateForeignKey;
            //---------------Test Result -----------------------
            Assert.IsFalse(canCreateFK);
        } 

        [Test]
        public void Test_CanCreateKFWhenAreObjectsIDValidFalse_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            ownerClass.ObjectIdentity.Properties.RemoveAll(property => true);
            DMProperty pkProp = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            pkProp.PropertyName = relatedClass.ClassNameBO + "ID";
            pkProp.Save();
            //---------------Assert Precondition----------------
            Assert.IsFalse(creator.Relationship.AreObjectIDsValid);
            Assert.IsTrue(creator.CanFindForeignKey);
            //---------------Execute Test ----------------------
            var canCreateFK = creator.CanCreateForeignKey;
            //---------------Test Result -----------------------
            Assert.IsFalse(canCreateFK);
        }

        [Test]
        public void Test_CanCreateKFWhenCanFindForeignKeyFalseAndObjectIDValidTrue_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            //---------------Assert Precondition----------------
            Assert.IsTrue(creator.AreObjectIDsValid);
            Assert.IsFalse(creator.CanFindForeignKey);
            //---------------Execute Test ----------------------
            var canCreateFK = creator.CanCreateForeignKey;
            //---------------Test Result -----------------------
            Assert.IsTrue(canCreateFK);
        }
        [Test]
        public void Test_CanCreateKFWhenCompositePrimaryKey_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DMObjectIdentity identity = TestUtilsDMObjectIdentity.CreateUnsavedValidCompositeDMObjectIdentity();
            DMClass ownerClass = identity.Class;
            DMClass relatedClass = TestUtilsDMClass.CreateDMClassWithObjectIdentity(ownerClass.Solution);
            relatedClass.Save();
            ownerClass.Save();
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass) { RelatedDMClass = relatedClass };
            //---------------Assert Precondition----------------
            Assert.IsTrue(creator.AreObjectIDsValid);
            Assert.IsFalse(creator.CanFindForeignKey);
            Assert.AreEqual(2, ownerClass.ObjectIdentity.Properties.Count);
            //---------------Execute Test ----------------------
            var canCreateFK = creator.CanCreateForeignKey;
            //---------------Test Result -----------------------
            Assert.IsFalse(canCreateFK);
        }
        [Test]
        public void Test_CanCreateKFWhenRelatedClassHasCompositePrimaryKey_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DMObjectIdentity identity = TestUtilsDMObjectIdentity.CreateUnsavedValidCompositeDMObjectIdentity();
            DMClass relatedClass = identity.Class;
            DMClass ownerClass = TestUtilsDMClass.CreateDMClassWithObjectIdentity(relatedClass.Solution);
            relatedClass.Save();
            ownerClass.Save();
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass) { RelatedDMClass = relatedClass };

            //---------------Assert Precondition----------------
            Assert.IsTrue(creator.AreObjectIDsValid);
            Assert.IsFalse(creator.CanFindForeignKey);
            Assert.AreEqual(2, relatedClass.ObjectIdentity.Properties.Count);
            //---------------Execute Test ----------------------
            var canCreateFK = creator.CanCreateForeignKey;
            //---------------Test Result -----------------------
            Assert.IsFalse(canCreateFK);
        }
                
        [Test]
        public void Test_SetUpRelationship_WhenCompositePrimaryKey_MustSetupRelationshipWithNoRelProps()
        {
            DMObjectIdentity identity = TestUtilsDMObjectIdentity.CreateUnsavedValidCompositeDMObjectIdentity();
            DMClass ownerClass = identity.Class;
            DMClass relatedClass = TestUtilsDMClass.CreateDMClassWithObjectIdentity(ownerClass.Solution);
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass) { RelatedDMClass = relatedClass };
            const Cardinality expectedRelCardinality = Cardinality.Multiple;
            creator.RelationshipCardinality = RelationshipCardinality.OneToMany;
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, ownerClass.ObjectIdentity.Properties.Count);
            Assert.IsFalse(creator.CanFindForeignKey);
            Assert.IsFalse(creator.MustCreateForeignKeyProp);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(0, creator.Relationship.RelationshipProperties.Count);
            Assert.AreEqual(expectedRelCardinality, creator.Relationship.Cardinality);
            Assert.IsNotNull(creator.Relationship.RelationshipName);

            //ReverseRelationship
            var reverseRelationship = creator.Relationship.ReverseRelationship;
            Assert.AreEqual(Cardinality.Single, reverseRelationship.Cardinality);
            Assert.IsNotNull(reverseRelationship.RelationshipName);
        }

        [Test]
        public void Test_HasExistingRelationshipBetweenClasses_WhenHasShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            DMObjectIdentity identity = TestUtilsDMObjectIdentity.CreateUnsavedValidCompositeDMObjectIdentity();
            DMClass ownerClass = identity.Class;
            DMClass relatedClass = TestUtilsDMClass.CreateDMClassWithObjectIdentity(ownerClass.Solution);
            new DMRelationshipCreator(ownerClass) { RelatedDMClass = relatedClass };
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass) { RelatedDMClass = relatedClass };
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, ownerClass.RelationshipsDM.Count);
            //---------------Execute Test ----------------------
            var hasExistingRel = creator.HasExistingRelationshipBetweenClasses;
            //---------------Test Result -----------------------
            Assert.IsTrue(hasExistingRel);
        }
        [Test]
        public void Test_HasExistingRelationshipBetweenClasses_WhenNotHas_ShouldReturnFalse()
        {
            //---------------Set up test pack-------------------
            DMObjectIdentity identity = TestUtilsDMObjectIdentity.CreateUnsavedValidCompositeDMObjectIdentity();
            DMClass ownerClass = identity.Class;
            DMClass relatedClass = TestUtilsDMClass.CreateDMClassWithObjectIdentity(ownerClass.Solution);
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass) { RelatedDMClass = relatedClass };
            const RelationshipCardinality expectedRelCardinality = RelationshipCardinality.OneToMany;
            creator.RelationshipCardinality = expectedRelCardinality;
            
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, ownerClass.RelationshipsDM.Count);
            //---------------Execute Test ----------------------
            var hasExistingRel = creator.HasExistingRelationshipBetweenClasses;
            //---------------Test Result -----------------------
            Assert.IsFalse(hasExistingRel);
        }

        [Test]
        public void Test_SetupRelationship_WhenHasRelatedFK_WhenFKIsUniqueConstraint_ShouldCreateOneToOne()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(ownerClass);
            property.PropertyName = relatedClass.ClassNameBO + "ID";
            relatedClass.CreateUnsavedUniqueConstraint(new List<DMProperty> { property });

            DMProperty foundProperty = creator.FindOwnerForeignKeyProp();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(property, foundProperty);
            Assert.AreEqual(1, relatedClass.UniqueConstraints.Count);
            Assert.IsTrue(property.IsPartOfSingleUniqueConstraint);
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            //---------------Test Result -----------------------
            Assert.AreEqual(Cardinality.Single ,creator.Relationship.Cardinality);
            Assert.AreEqual(Cardinality.Single ,creator.Relationship.ReverseRelationship.Cardinality);
        }

        [Test]
        public void Test_RelationshipSetup_WhenSetupRelationshipCalled_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            //---------------Assert Precondition----------------
            Assert.IsFalse(creator.IsRelationshipSetup);            
            //---------------Execute Test ----------------------
            creator.SetupRelationship();
            var isRelationshipSetup = creator.IsRelationshipSetup;
            //---------------Test Result -----------------------
            Assert.IsTrue(isRelationshipSetup);
            Assert.IsTrue(creator.CanFindForeignKey);
        }
        [Test]
        public void Test_RelationshipSetup_WhenCancelCreatedProperties_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DMClass ownerClass;
            DMClass relatedClass;
            DMRelationshipCreator creator = CreateCreatorWithTwoClasses(out ownerClass, out relatedClass);
            creator.SetupRelationship();
            //---------------Assert Precondition----------------
            Assert.IsTrue(creator.IsRelationshipSetup);
            Assert.IsTrue(creator.CanFindForeignKey);
            //---------------Execute Test ----------------------
            creator.CancelCreatedProperties();
            var isRelationshipSetup = creator.IsRelationshipSetup;
            //---------------Test Result -----------------------
            Assert.IsFalse(isRelationshipSetup);
            Assert.IsFalse(creator.CanFindForeignKey);
        }

        private static DMRelationshipCreator CreateCreatorWithTwoClasses(out DMClass ownerClass,
                                                                         out DMClass relatedClass)
        {
            ownerClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            TestUtilsShared.CreateSavedObjectIdentityInfo(ownerClass);
            relatedClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            TestUtilsShared.CreateSavedObjectIdentityInfo(relatedClass);
            DMRelationshipCreator creator = new DMRelationshipCreator(ownerClass) {RelatedDMClass = relatedClass};
            return creator;
        }

        private static DMRelationshipCreatorStub CreateCreatorStubWithTwoClasses(out DMClass ownerClass,
                                                                                 out DMClass relatedClass)
        {
            ownerClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            TestUtilsShared.CreateSavedObjectIdentityInfo(ownerClass);
            relatedClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            TestUtilsShared.CreateSavedObjectIdentityInfo(relatedClass);
            DMRelationshipCreatorStub creator = new DMRelationshipCreatorStub(ownerClass)
                                                    {RelatedDMClass = relatedClass};
            return creator;
        }

        private static void AssertCardinalityMultiple(DMRelationshipCreator creator)
        {
            Assert.AreEqual(Cardinality.Multiple, creator.Relationship.Cardinality);
        }
        private static void AssertCardinalityMultiple(DMRelationship reverseRelationship)
        {
            Assert.AreEqual(Cardinality.Multiple, reverseRelationship.Cardinality);
        }
        private static void AssertCardinalitySingle(IDMRelationship relationship)
        {
            Assert.AreEqual(Cardinality.Single, relationship.Cardinality);
        }
        private static void AssertRelationshipCardinalityManyToOne(DMRelationshipCreator creator)
        {
            Assert.AreEqual(RelationshipCardinality.ManyToOne, creator.RelationshipCardinality);
        }
        private class DMRelationshipCreatorStub : DMRelationshipCreator
        {
            public DMRelationshipCreatorStub(DMClass ownerClass) : base(ownerClass)
            {
            }

            internal DMProperty TestCreateFKProperty(DMClass ownerClass, DMClass relatedClass)
            {
                return base.CreateFKProperty(ownerClass, relatedClass);
            }
        }
    }
}